package se.webbzon.boltzmann.game.object.portal;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

import javax.media.j3d.Transform3D;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Vector3d;

import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.worldobject.appearance.Appearance3D;
import se.webbzon.oschi01.worldobject.appearance.GroupAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.YZPlaneAppearance3D;

public class SingleDoor extends AbstractDoor {
	
	// The maximal angle of the door when it is open
	private static final double maxAngle = 0.75 * Math.PI;
	
	// Whatever this door is aligned to the left
	private final boolean leftDoor;
	
	// The hinge of this door
	private final Appearance3D hinge;
	
	/*============================================================
	Constructor
	============================================================*/
	
	/** Creates a new left door with the given texture set. **/
	public SingleDoor(boolean leftDoor, boolean indoor, String textureSetName, Color textureBlending) {
		super(new GroupAppearance3D(0,/*GroupAppearance3D.EXTENDING*/0,null));
		this.leftDoor = leftDoor;
		
		// The rendering order of the door
		final int renderingOrder = indoor ? 1 : 0;
		// Whatever the hinge should be on the left side (relative to the camera)
		final boolean leftHinge = leftDoor ^ indoor;
		
		GroupAppearance3D appearance = (GroupAppearance3D) getAppearance();
		
		final Transform3D transform = new Transform3D();
		final Vector3d vector = new Vector3d();
		final AxisAngle4d rotation = new AxisAngle4d(0,1,0,Math.PI);
		transform.setRotation(rotation);
		
		// Add a background if not indoor
		if (!indoor) {
			SimpleAppearance3D background = new YZPlaneAppearance3D(0,SimpleAppearance3D.LAYERS,false);
			background.setLayer(-1/16.0, 0, 0);
			background.setColor(Color.black);
			vector.set(0.5, 0, 0);
			transform.setTranslation(vector);

			background.setTransform(transform);
			appearance.addAppearance(background);
		}
		
		// Add hinge group
		List<Appearance3D> appearances = new ArrayList<Appearance3D>();
		
		// Create front door
		{
			SimpleAppearance3D doorFront = new YZPlaneAppearance3D(renderingOrder,
											SimpleAppearance3D.LAYERS + 
											SimpleAppearance3D.TEXTURE_REPEATING +
											SimpleAppearance3D.TRANSPARENCY, false);
			doorFront.setTextureSet(Resources.getTextureSet(textureSetName));
			doorFront.setColor(textureBlending);
			doorFront.setLayer(-3/16.0, 0, 0);
			doorFront.setHRep(indoor ? 1 : -1);
			vector.set(0, 0, leftHinge ? 0.5 : -0.5);
			transform.setTranslation(vector);
			doorFront.setTransform(transform);
			appearances.add(doorFront);
			if (indoor)
				doorFront.setTransparency(0.5f);
		}
		
		// Create back door
		{
			SimpleAppearance3D doorBack = new YZPlaneAppearance3D(renderingOrder,
											SimpleAppearance3D.LAYERS +
											SimpleAppearance3D.TEXTURE_REPEATING +
											SimpleAppearance3D.TRANSPARENCY, false);
			doorBack.setTextureSet(Resources.getTextureSet(textureSetName));
			doorBack.setColor(textureBlending);
			doorBack.setLayer(-3/16.0, 0, 0);
			doorBack.setHRep(indoor ? -1 : 1);
			vector.set(0, 0, leftHinge ? 0.5 : -0.5);
			rotation.set(0,1,0,0);
			transform.setTranslation(vector);
			transform.setRotation(rotation);
			doorBack.setTransform(transform);
			appearances.add(doorBack);
			if (indoor)
				doorBack.setTransparency(0.5f);
		}
		
		// Add hinge
		hinge = new GroupAppearance3D(0,appearances);
		vector.set(0.5, 0, leftHinge ? -0.5 : 0.5);
		transform.setTranslation(vector);
		hinge.setTransform(transform);
		
		appearance.addAppearance(hinge);
	}
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override public void onUpdate(double p) {
		final Transform3D transform = new Transform3D();
		final double v = leftDoor ? -p : p;
		final AxisAngle4d rotation = new AxisAngle4d(0,1,0,v * maxAngle);
		hinge.getTransform(transform);
		transform.setRotation(rotation);
		hinge.setTransform(transform);
	}
	
}
